package com.phil.philreports.asynccelltablesearch.client;

import java.util.Iterator;
import java.util.Set;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.Range;
import com.phil.philreports.asynccelltablesearch.client.data.ClientPerson;
import com.phil.philreports.asynccelltablesearch.client.data.ClientPersons;
import com.phil.philreports.asynccelltablesearch.client.service.GetPersonsService;
import com.phil.philreports.asynccelltablesearch.client.service.GetPersonsServiceAsync;

public class PersonsView implements EntryPoint {
	
	// service
	private GetPersonsServiceAsync getPersonsService;
	private AsyncCallback<ClientPersons> cbPersons;
	private AsyncCallback<String> cbTestData;
	private AsyncDataProvider<ClientPerson> dataProvider;
	
	// data
	private ClientPersons data;
	private String search;
	
	// visible area
	private int start = 0;
	private int length = 10;
	
	// building blocks
	private RootPanel rootPanel;
	private VerticalPanel vp;
	
	private Button generateTestDataButton;
	private TextBox searchText;
	private Button searchTextButton;
	private CellTable<ClientPerson> table;
	private SimplePager pager;
	
	public void onModuleLoad() {
		// remote services
		getPersonsService = GWT.create(GetPersonsService.class);
		
		// init data object
		data = new ClientPersons();
		search = "";
		
		// create the table
		table = new CellTable<ClientPerson>();
		table.setPageSize(this.length);
		
		// create the columns
		TextColumn<ClientPerson> colFirstName = new TextColumn<ClientPerson>() {
			@Override
			public String getValue(ClientPerson object) {
				return object.getFirstname();
			}
		};
		TextColumn<ClientPerson> colLastName = new TextColumn<ClientPerson>() {
			@Override
			public String getValue(ClientPerson object) {
				return object.getLastname();
			}
		};
		TextColumn<ClientPerson> colEmail = new TextColumn<ClientPerson>() {
			@Override
			public String getValue(ClientPerson object) {
				return object.getEmail();
			}
		};
		
		// add the columns to the table
		table.addColumn(colFirstName, "First name");
		table.addColumn(colLastName, "Last name");
		table.addColumn(colEmail, "Email");
		
		// the data provider
		dataProvider = new AsyncDataProvider<ClientPerson>() {
			@Override
			protected void onRangeChanged(HasData<ClientPerson> display) {
				
				start = display.getVisibleRange().getStart();
				
				length = display.getVisibleRange().getLength();
				// the async call
				cbPersons = new AsyncCallback<ClientPersons>() {
					@Override
					public void onFailure(Throwable caught) {
						
					}
					@Override
					public void onSuccess(ClientPersons result) {
						data = result;
						if(data.getPersons().size() < length) {
							// we are on the last page and know the size
							updateRowCount(data.getPersons().size()+start, true);
						}
						updateRowData(start, data.getPersons());
					}
				};
				// make the call
				System.out.println("getPersonsService.getPersons("+start+", "+length+", search, cbPersons);");
				getPersonsService.getPersons(start, length, search, cbPersons);
			}
		};
		// link the data provider to the table
		dataProvider.addDataDisplay(table);
		
		// the pager
		pager = new SimplePager();
		pager.setDisplay(table);
		
		
		// generate test data
		generateTestDataButton = new Button("generate Test Data");
		
		cbTestData = new AsyncCallback<String>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Failed to generate test data");
			}
			@Override
			public void onSuccess(String result) {
				Window.alert("Test data created" + result);
				data = new ClientPersons();
				search = "";
				searchText.setText("");
				start=0;
				dataProvider.updateRowCount(0, false);
				
				Set<HasData<ClientPerson>> dataDisplays = dataProvider.getDataDisplays();
				Iterator<HasData<ClientPerson>> dataDisplaysIter = dataDisplays.iterator();
				while(dataDisplaysIter.hasNext()) {
					HasData<ClientPerson> display = dataDisplaysIter.next();
					display.setVisibleRangeAndClearData(new Range(start, length), true);
				}
				
				getPersonsService.getPersons(start, length, search, cbPersons);
			}
		};
		generateTestDataButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				getPersonsService.generateTestData(100, cbTestData);
			}
		});
		
		
		// search box
		searchText = new TextBox();
		searchTextButton = new Button("search");
		
		searchTextButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				data = new ClientPersons();
				search = searchText.getText().trim();
				searchText.setText(search);
				start=0;
				dataProvider.updateRowCount(0, false);
				
				Set<HasData<ClientPerson>> dataDisplays = dataProvider.getDataDisplays();
				Iterator<HasData<ClientPerson>> dataDisplaysIter = dataDisplays.iterator();
				while(dataDisplaysIter.hasNext()) {
					HasData<ClientPerson> display = dataDisplaysIter.next();
					display.setVisibleRangeAndClearData(new Range(start, length), true);
				}
				
				getPersonsService.getPersons(start, length, search, cbPersons);
				
			}
		});
		
		
		
		// put everything together
		vp = new VerticalPanel();
		
		vp.add(generateTestDataButton);
		vp.add(searchText);
		vp.add(searchTextButton);
		vp.add(table);
		vp.add(pager);
		
		rootPanel = RootPanel.get("personsTable");
		
		rootPanel.add(vp);
	}

}
